package com.lenovo.agricultureServer.Serial;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import com.lenovo.agricultureServer.MainActivity;
import com.lenovo.agricultureServer.bean.Controller;
import com.lenovo.agricultureServer.bean.Sensor;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android_serialport_api.ZigbeeAdapter;

// 串口读写service类, 作为service在后台运行
public class SerialportService extends Service 
{
	private static final String TAG = "SerialportService";
	
	public static boolean ifSIMULATE = false;// 是否模拟
	private static ArrayList<Sensor> gSensorList = new ArrayList<Sensor>(); //传感器数组
	private static ArrayList<Controller> gControllerList = new ArrayList<Controller>(); //控制器数组
	
	private MyHandler handler = null;
	private ZigbeeAdapter adapter;
	private Timer timer;
	private SendToSerialportServiceBroadcast mBroadcast;
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@SuppressWarnings("deprecation")
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		try {
			//初始化传感器数组
			gSensorList.clear();
			gSensorList.add(new Sensor(Sensor.PM25_SENSOR, 0x00));
			gSensorList.add(new Sensor(Sensor.CO2_SENSOR, 0x00));
			gSensorList.add(new Sensor(Sensor.AIR_TMPER_SENSOR, 0x00));
			gSensorList.add(new Sensor(Sensor.AIR_HUMID_SENSOR, 0x01));
			gSensorList.add(new Sensor(Sensor.SOIL_TMPER_SENSOR, 0x00));
			gSensorList.add(new Sensor(Sensor.SOIL_HUMID_SENSOR, 0x01));
			gSensorList.add(new Sensor(Sensor.LIGHT_SENSOR, 0x00));
			
			//初始化控制器数组
			gControllerList.clear();
			gControllerList.add(new Controller(Controller.WATER_PUMP_CONTORL, 0x00));
			gControllerList.add(new Controller(Controller.BLOWER_CONTORL, 0x01));
			gControllerList.add(new Controller(Controller.BUZZER_CONTORL, 0x02));
			gControllerList.add(new Controller(Controller.ROADLAMP_CONTORL, 0x03));
			
			handler = new MyHandler();
			// 创建 ZigbeeAdapter对象
			adapter = new ZigbeeAdapter(handler);
			// 调用接口，初始化外接Zigbee串口模块
			adapter.initSerial(MainActivity.devices[MainActivity.chose], 115200);
			// 调用外部接口，对外部Zigbee模块执行协议握手
			adapter.devHands();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("gdevHands...,waiting for device address. ");
		// 启动定时器，周期性向外部设备请求传感数据。包括co2和pm2.5
		timer = new Timer();
		timer.schedule(new CO2SensorTask(), 1000, 1000);
		System.out.println("Serial Service Started. ");
	}

	@Override
	public void onCreate() {
		super.onCreate();
		mBroadcast = new SendToSerialportServiceBroadcast();
		IntentFilter intentFilter = new IntentFilter();  
        intentFilter.addAction("com.lenovo.agriculture.server.broadcat.senttoserialport");  
        registerReceiver(mBroadcast, intentFilter); 
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		// 释放定时器资源
		if (timer != null) {
			timer.cancel();
		}
		// 释放串口资源
		adapter.closeSerial();
		if(mBroadcast!=null)
		{
			unregisterReceiver(mBroadcast);
		}
		Log.d(TAG,"Serial Service Stopped.");
	}

	// 处理来自外部设备上报的传感数据
	@SuppressLint("HandlerLeak")
	public final class MyHandler extends Handler 
	{
		public void handleMessage(Message msg) 
		{
			byte[] addr = null;
			switch (msg.what) 
			{
			case 1:
				// 获取外接多个传感模块地址，用于后续对该模块进行数据请求
				String nameStr = msg.getData().getString("sensorName"); //获取传感器名称
				addr = msg.getData().getByteArray("sensorAddr");//获取传感器地址
				if(addr!=null && nameStr!=null)
				{
					Log.d(TAG,"get sensor name : "+nameStr+", addr :"+addr);
					//处理pm2.5, Co2和灯光传感器的地址
					if(nameStr.equals(Sensor.PM25_SENSOR)
						||nameStr.equals(Sensor.CO2_SENSOR)
						||nameStr.equals(Sensor.LIGHT_SENSOR))
					{
						//根据传感器名称设置传感器地址
						Sensor sensor = Sensor.getSensorByName(gSensorList, nameStr);
						if(sensor != null)
						{
							sensor.setAddr(addr);
						}
					}
					
					//处理空气温湿度传感器的地址,它们共用一个地址
					if(nameStr.equals(Sensor.AIR_TMPER_SENSOR))
					{
						Sensor sensor = Sensor.getSensorByName(gSensorList, nameStr);
						if(sensor != null)
						{
							sensor.setAddr(addr);
						}
						sensor = Sensor.getSensorByName(gSensorList, Sensor.AIR_HUMID_SENSOR);
						if(sensor != null)
						{
							sensor.setAddr(addr);
						}
					}
					
					//处理土壤温湿度传感器的地址,它们共用一个地址
					if(nameStr.equals(Sensor.SOIL_TMPER_SENSOR))
					{
						Sensor sensor = Sensor.getSensorByName(gSensorList, nameStr);
						if(sensor != null)
						{
							sensor.setAddr(addr);
						}
						sensor = Sensor.getSensorByName(gSensorList, Sensor.SOIL_HUMID_SENSOR);
						if(sensor != null)
						{
							sensor.setAddr(addr);
						}
					}
					
					//处理控制器的地址
					if(nameStr.equals(Controller.WATER_PUMP_CONTORL) && gControllerList.get(0).getAddr()==null)
					{
						//所有的控制器都共用一个地址
						for(Controller controller : gControllerList)
						{
							controller.setAddr(addr);
							//获得控制器地址时，先关闭控制器
							adapter.controlAct(controller.getAddr(), controller.getSubDev(), 0x30);
							controller.setStatus(0);
							threadWait();//延时，预留时间给下位机处理
						}
					}
				}
				break;
			
			case 2:
				// 获取传感器上报数据
				addr = msg.getData().getByteArray("sensorAddr");//获取传感器地址
				byte[] dataByte = msg.getData().getByteArray("sensorData");//获取传感器数据
				int nSub = msg.getData().getInt("SubNum"); //获取子设备地址
				if(addr!=null && dataByte!=null)
				{
					String addrStr = ZigbeeAdapter.Bytes2HexString(addr);
					try 
					{
						float fi = Float.parseFloat(new String(dataByte));//解析传感器数据
						int value = (int) fi;
						boolean isSuccess = false;
						for(Sensor sensor : gSensorList)
						{
							//先判断地址是否为空
							if(sensor.getAddr()==null){
								continue;
							}
							//遍历传感器列表，根据地址找到对应的传感器并设置对应的值
							if(addrStr.equals(ZigbeeAdapter.Bytes2HexString(sensor.getAddr()))
								&& sensor.getSubDev()==nSub)
							{
								sensor.setValue(value);
								isSuccess = true;
								//Log.d(TAG, "recv "+sensor.getName()+"("+addr+") data : "+sensor.getValue());
							}
						}
						if(!isSuccess){
							//发现未知设备的数据，通过日志打印出来
							Log.e(TAG,"recv unknown sensor, addr : "+addrStr);
						}
					} catch (NumberFormatException e) {
						e.printStackTrace();
					} catch (Exception e){
						e.printStackTrace();
					}
				}
				break;
			default:
				break;
			}
		}
	};
	
	//根据控制器名称打开相应的控制器
	public void openControllerByName(String name)
	{
		Controller controller = Controller.getControllerByName(gControllerList, name); //找到控制器
		if(controller!=null 				
			&& controller.getAddr()!=null)  // 并且控制器的地址不能为空
			//&& !controller.isStateON())    // 并且控制器当前不是打开状态
		{
			adapter.controlAct(controller.getAddr(), controller.getSubDev(), 0x31);
			controller.setStatus(1);
		}
	}
	
	//根据控制器名称关闭相应的控制器
	public void closeControllerByName(String name)
	{
		Controller controller = Controller.getControllerByName(gControllerList, name); //找到控制器
		if(controller!=null 				
			&& controller.getAddr()!=null)  // 并且控制器的地址不能为空
			//&& !controller.isStateON())    // 并且控制器当前必须是打开状态
		{
			adapter.controlAct(controller.getAddr(), controller.getSubDev(), 0x30);
			controller.setStatus(0);
		}
	}
	
	//线程等待
	public void threadWait()
	{
		try {
			Thread.sleep(500);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 定时发送消息给外部设备，请求传感数据，包括PM2.5和co2
	class CO2SensorTask extends TimerTask {
		@Override
		public void run() {
			if (ifSIMULATE) 
			{
				for(Sensor sensor : gSensorList)
				{
					sensor.setValue((int) (System.currentTimeMillis() % 99));
				}
			} 
			else 
			{
				//分别获取当前所有传感器的数据
				for(Sensor sensor : gSensorList)
				{
					if(sensor.getAddr()==null){
						continue;
					}
					adapter.RequestDeviceData(sensor.getAddr(), (byte) sensor.getSubDev());
				}
			}
		}
	};

	public static int getSensorValueByName(String name)
	{
		Sensor sensor = Sensor.getSensorByName(gSensorList, name);
		if(sensor!=null){
			return sensor.getValue();
		} else {
			return -1;
		}
	}
	
	public static int getControllerStatusByName(String name)
	{
		int status = 0;
		Controller controller = Controller.getControllerByName(gControllerList, name);
		if(controller != null){
			status = controller.getStatus();
		}
		return status;
	}
	
	/*
	 * BroadcastReceiver也就是“广播接收者”的意思，顾名思义，它就是用来接收来自系统和应用中的广播。
	 * 在Android系统中，广播体现在方方面面，例如当开机完成后系统会产生一条广播，接收到这条广播就能实现开机启动服务的功能；
	 * 当网络状态改变时系统会产生一条广播，接收到这条广播就能及时地做出提示和保存数据等操作；当电池电量改变时，
	 * 系统会产生一条广播，接收到这条广播就能在电量低时告知用户及时保存进度，等等。
	 * Android中的广播机制设计的非常出色，很多事情原本需要开发者亲自操作的，
	 * 现在只需等待广播告知自己就可以了，大大减少了开发的工作量和开发周期。
	 */
	class SendToSerialportServiceBroadcast extends BroadcastReceiver
	{
		@Override
		public void onReceive(Context context, Intent intent) 
		{
			//用来接收http server或socket server的控制信息
			String message = intent.getStringExtra("message");
			String device = intent.getStringExtra("device");
			int isOpen = intent.getIntExtra("isOpen", -1); //0 close control, 1 open control
			Log.d(TAG,"Broadcast recevie : "+message+","+device+","+isOpen);
			
			if(message.equals("control"))
			{
				if(isOpen == 1){
					openControllerByName(device);
				} else if(isOpen == 0) {
					closeControllerByName(device);
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}
